package com.rickpan.service;

import com.rickpan.entity.TransferRecord;
import com.rickpan.repository.TransferRecordRepository;
import com.rickpan.event.TransferEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 传输记录服务
 */
@Service
@Transactional
public class TransferRecordService {

    private static final Logger logger = LoggerFactory.getLogger(TransferRecordService.class);

    // 进度变化阈值，避免频繁推送Socket.IO事件
    private static final int PROGRESS_THRESHOLD = 1; // 1%

    @Autowired
    private TransferRecordRepository transferRecordRepository;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    /**
     * 创建传输记录
     */
    public TransferRecord createTransferRecord(Long userId, String fileName, String originalName, 
                                             Long fileSize, String sessionId) {
        TransferRecord record = new TransferRecord();
        record.setUserId(userId);
        record.setFileName(fileName);
        record.setOriginalName(originalName);
        record.setFileSize(fileSize);
        record.setTransferType(TransferRecord.TransferType.UPLOAD);
        record.setTransferStatus(TransferRecord.TransferStatus.PENDING);
        record.setSessionId(sessionId);
        record.setStartTime(LocalDateTime.now());

        TransferRecord saved = transferRecordRepository.save(record);
        // 记录传输记录创建（生产环境可考虑调整为DEBUG级别）
        logger.info("创建传输记录: recordId={}, fileName={}, userId={}",
                   saved.getId(), originalName, userId);

        // 立即发布传输创建事件，确保前端能立即看到传输记录（解决渲染延迟问题）
        eventPublisher.publishEvent(new TransferEvent.TransferProgressEvent(this, saved));

        return saved;
    }

    /**
     * 保存传输记录（用于前端直接创建记录）
     */
    public TransferRecord saveTransferRecord(TransferRecord record) {
        TransferRecord saved = transferRecordRepository.save(record);

        logger.info("保存传输记录: recordId={}, fileName={}, userId={}, type={}, status={}",
                   saved.getId(), saved.getOriginalName(), saved.getUserId(),
                   saved.getTransferType(), saved.getTransferStatus());

        // 发布传输事件
        eventPublisher.publishEvent(new TransferEvent.TransferProgressEvent(this, saved));

        return saved;
    }

    /**
     * 开始传输
     */
    public void startTransfer(Long recordId) {
        Optional<TransferRecord> optionalRecord = transferRecordRepository.findById(recordId);
        if (optionalRecord.isPresent()) {
            TransferRecord record = optionalRecord.get();
            record.setTransferStatus(TransferRecord.TransferStatus.IN_PROGRESS);
            record.setStartTime(LocalDateTime.now());
            
            transferRecordRepository.save(record);

            // 发布传输开始事件
            eventPublisher.publishEvent(new TransferEvent.TransferProgressEvent(this, record));
            
            // 记录传输开始信息
            logger.info("开始传输: recordId={}, fileName={}", recordId, record.getOriginalName());
        }
    }

    /**
     * 更新传输进度
     */
    public void updateTransferProgress(Long recordId, Long transferredBytes, Long speed) {
        Optional<TransferRecord> optionalRecord = transferRecordRepository.findById(recordId);
        if (optionalRecord.isPresent()) {
            TransferRecord record = optionalRecord.get();

            // 计算新的进度百分比
            BigDecimal newProgress = BigDecimal.valueOf(transferredBytes)
                    .multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(record.getFileSize()), 2, BigDecimal.ROUND_HALF_UP);

            // 获取旧的进度
            BigDecimal oldProgress = record.getProgressPercentage();

            // 检查进度变化是否超过阈值
            boolean shouldPublishEvent = false;
            if (oldProgress == null) {
                shouldPublishEvent = true; // 首次更新
            } else {
                int progressDiff = Math.abs(newProgress.intValue() - oldProgress.intValue());
                shouldPublishEvent = progressDiff >= PROGRESS_THRESHOLD;
            }

            // 更新记录
            record.setTransferredBytes(transferredBytes);
            record.setProgressPercentage(newProgress);
            record.setTransferSpeed(speed);

            transferRecordRepository.save(record);

            // 只有进度变化超过阈值才发布事件
            if (shouldPublishEvent) {
                eventPublisher.publishEvent(new TransferEvent.TransferProgressEvent(this, record));
                logger.debug("发布传输进度事件: recordId={}, progress={}%, diff={}%",
                           recordId, newProgress, oldProgress != null ?
                           newProgress.intValue() - oldProgress.intValue() : newProgress.intValue());
            }
        }
    }

    /**
     * 完成传输
     */
    public void completeTransfer(Long recordId, String filePath) {
        Optional<TransferRecord> optionalRecord = transferRecordRepository.findById(recordId);
        if (optionalRecord.isPresent()) {
            TransferRecord record = optionalRecord.get();
            record.setTransferStatus(TransferRecord.TransferStatus.COMPLETED);
            record.setProgressPercentage(BigDecimal.valueOf(100));
            record.setTransferredBytes(record.getFileSize());
            record.setEndTime(LocalDateTime.now());
            record.setFilePath(filePath);
            
            transferRecordRepository.save(record);

            // 发布传输完成事件
            eventPublisher.publishEvent(new TransferEvent.TransferCompletedEvent(this, record));
            
            // 记录传输完成信息
            logger.info("传输完成: recordId={}, fileName={}", recordId, record.getOriginalName());
        }
    }

    /**
     * 传输失败
     */
    public void failTransfer(Long recordId, String errorMessage) {
        Optional<TransferRecord> optionalRecord = transferRecordRepository.findById(recordId);
        if (optionalRecord.isPresent()) {
            TransferRecord record = optionalRecord.get();
            record.setTransferStatus(TransferRecord.TransferStatus.FAILED);
            record.setEndTime(LocalDateTime.now());
            record.setErrorMessage(errorMessage);
            
            transferRecordRepository.save(record);

            // 发布传输失败事件
            eventPublisher.publishEvent(new TransferEvent.TransferFailedEvent(this, record));
            
            logger.error("❌ 传输失败: recordId={}, fileName={}, error={}", 
                        recordId, record.getOriginalName(), errorMessage);
        }
    }

    /**
     * 获取用户的传输历史记录
     */
    public Page<TransferRecord> getTransferHistory(Long userId, int page, int size) {
        return getTransferHistory(userId, page, size, "all");
    }

    /**
     * 获取用户的传输历史记录（支持筛选）
     */
    public Page<TransferRecord> getTransferHistory(Long userId, int page, int size, String filter) {
        Pageable pageable = PageRequest.of(page, size);

        if ("COMPLETED".equals(filter)) {
            return transferRecordRepository.findByUserIdAndTransferStatusOrderByCreatedAtDesc(
                    userId, TransferRecord.TransferStatus.COMPLETED, pageable);
        } else if ("FAILED".equals(filter)) {
            return transferRecordRepository.findByUserIdAndTransferStatusOrderByCreatedAtDesc(
                    userId, TransferRecord.TransferStatus.FAILED, pageable);
        } else {
            // "all" 或其他值，返回所有记录
            return transferRecordRepository.findByUserIdOrderByCreatedAtDesc(userId, pageable);
        }
    }

    /**
     * 获取用户当前进行中的传输
     */
    public List<TransferRecord> getActiveTransfers(Long userId) {
        return transferRecordRepository.findActiveTransfersByUserId(userId);
    }

    /**
     * 获取今日传输记录
     */
    public List<TransferRecord> getTodayTransfers(Long userId) {
        return transferRecordRepository.findTodayTransfersByUserId(userId);
    }

    /**
     * 清除已完成的传输记录
     */
    public void clearCompletedRecords(Long userId) {
        List<TransferRecord> completedRecords = transferRecordRepository
                .findByUserIdAndTransferStatusOrderByCreatedAtDesc(
                        userId, TransferRecord.TransferStatus.COMPLETED);
        
        transferRecordRepository.deleteAll(completedRecords);
        logger.info("🗑️ 清除已完成传输记录: userId={}, count={}", userId, completedRecords.size());
    }

    /**
     * 根据会话ID查找传输记录（返回最新的一条）
     */
    public Optional<TransferRecord> findBySessionId(String sessionId) {
        return transferRecordRepository.findFirstBySessionIdOrderByCreatedAtDesc(sessionId);
    }

    /**
     * 线程安全的查找或创建传输记录
     */
    @Transactional
    public TransferRecord findOrCreateTransferRecord(Long userId, String sessionId, String fileName, Long fileSize) {
        try {
            // 使用数据库锁查找现有记录
            Optional<TransferRecord> existingRecord = transferRecordRepository.findFirstBySessionIdOrderByCreatedAtDesc(sessionId);

            if (existingRecord.isPresent()) {
                TransferRecord record = existingRecord.get();
                if (record.getUserId().equals(userId)) {
                    logger.debug("找到现有传输记录: recordId={}, sessionId={}", record.getId(), sessionId);
                    return record;
                } else {
                    logger.warn("传输记录用户不匹配: recordId={}, expectedUserId={}, actualUserId={}",
                               record.getId(), userId, record.getUserId());
                }
            }

            // 创建新记录，利用数据库唯一约束防止重复
            try {
                TransferRecord newRecord = createTransferRecord(userId, fileName, fileName, fileSize, sessionId);
                logger.info("创建新传输记录: recordId={}, sessionId={}, fileName={}",
                           newRecord.getId(), sessionId, fileName);
                return newRecord;
            } catch (Exception e) {
                // 如果创建失败（可能是唯一约束冲突），再次查找
                logger.warn("创建传输记录失败，尝试重新查找: sessionId={}", sessionId);
                Optional<TransferRecord> retryRecord = transferRecordRepository.findFirstBySessionIdOrderByCreatedAtDesc(sessionId);
                if (retryRecord.isPresent() && retryRecord.get().getUserId().equals(userId)) {
                    return retryRecord.get();
                }
                throw e;
            }

        } catch (Exception e) {
            logger.error("查找或创建传输记录失败: sessionId={}", sessionId, e);
            throw new RuntimeException("传输记录处理失败", e);
        }
    }

    /**
     * 更新传输记录
     */
    public void updateTransferRecord(TransferRecord record) {
        transferRecordRepository.save(record);
    }

    /**
     * 删除传输记录
     */
    public void deleteTransferRecord(Long recordId) {
        try {
            transferRecordRepository.deleteById(recordId);
            logger.info("传输记录已删除: recordId={}", recordId);
        } catch (Exception e) {
            logger.error("删除传输记录失败: recordId={}", recordId, e);
        }
    }

    /**
     * 发布传输完成事件
     */
    public void publishTransferCompletedEvent(TransferRecord record) {
        try {
            eventPublisher.publishEvent(new TransferEvent.TransferCompletedEvent(this, record));
            logger.debug("发布传输完成事件: recordId={}", record.getId());
        } catch (Exception e) {
            logger.warn("发布传输完成事件失败: recordId={}", record.getId(), e);
        }
    }

    /**
     * 获取传输统计信息
     */
    public TransferStatistics getTransferStatistics(Long userId) {
        long completedCount = transferRecordRepository.countByUserIdAndStatus(
                userId, TransferRecord.TransferStatus.COMPLETED);
        long failedCount = transferRecordRepository.countByUserIdAndStatus(
                userId, TransferRecord.TransferStatus.FAILED);
        long inProgressCount = transferRecordRepository.countByUserIdAndStatus(
                userId, TransferRecord.TransferStatus.IN_PROGRESS);

        return new TransferStatistics(completedCount, failedCount, inProgressCount);
    }

    /**
     * 传输统计信息内部类
     */
    public static class TransferStatistics {
        private final long completedCount;
        private final long failedCount;
        private final long inProgressCount;

        public TransferStatistics(long completedCount, long failedCount, long inProgressCount) {
            this.completedCount = completedCount;
            this.failedCount = failedCount;
            this.inProgressCount = inProgressCount;
        }

        public long getCompletedCount() { return completedCount; }
        public long getFailedCount() { return failedCount; }
        public long getInProgressCount() { return inProgressCount; }
        public long getTotalCount() { return completedCount + failedCount + inProgressCount; }
    }
}
